package com.hifar.sso.service.impl;

import com.hifar.sso.model.SSOToken;
import com.hifar.sso.service.SSOTokenService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * SSO令牌服务实现类（内存存储）
 * 
 * @author system
 * @since 1.0.0
 */
@Service
public class SSOTokenServiceImpl implements SSOTokenService {
    
    private static final Logger logger = LoggerFactory.getLogger(SSOTokenServiceImpl.class);
    
    // 内存存储 - 生产环境建议使用Redis
    private final Map<String, SSOToken> tokenStore = new ConcurrentHashMap<>();
    private final Map<String, SSOToken> refreshTokenStore = new ConcurrentHashMap<>();
    private final Map<String, SSOToken> authCodeStore = new ConcurrentHashMap<>();
    
    @Override
    public void storeToken(SSOToken token) {
        try {
            logger.debug("存储令牌: {}", token.getAccessToken());
            tokenStore.put(token.getAccessToken(), token);
            if (token.getRefreshToken() != null) {
                refreshTokenStore.put(token.getRefreshToken(), token);
            }
        } catch (Exception e) {
            logger.error("存储令牌异常", e);
            throw new RuntimeException("存储令牌失败", e);
        }
    }
    
    @Override
    public SSOToken getTokenByAccessToken(String accessToken) {
        try {
            logger.debug("获取访问令牌: {}", accessToken);
            return tokenStore.get(accessToken);
        } catch (Exception e) {
            logger.error("获取访问令牌异常", e);
            return null;
        }
    }
    
    @Override
    public SSOToken getTokenByRefreshToken(String refreshToken) {
        try {
            logger.debug("获取刷新令牌: {}", refreshToken);
            return refreshTokenStore.get(refreshToken);
        } catch (Exception e) {
            logger.error("获取刷新令牌异常", e);
            return null;
        }
    }
    
    @Override
    public void storeAuthorizationCode(String code, String username, String clientId, String redirectUri, String scope) {
        try {
            logger.debug("存储授权码: {}", code);
            SSOToken authCode = new SSOToken();
            authCode.setAccessToken(code);
            authCode.setUserId(username);
            authCode.setClientId(clientId);
            authCode.setScope(redirectUri);
            authCode.setCreateTime(new Date());
            authCode.setExpireTime(new Date(System.currentTimeMillis() + 10 * 60 * 1000)); // 10分钟过期
            authCodeStore.put(code, authCode);
        } catch (Exception e) {
            logger.error("存储授权码异常", e);
            throw new RuntimeException("存储授权码失败", e);
        }
    }
    
    @Override
    public SSOToken getAuthorizationCode(String code) {
        try {
            logger.debug("获取授权码: {}", code);
            return authCodeStore.get(code);
        } catch (Exception e) {
            logger.error("获取授权码异常", e);
            return null;
        }
    }
    
    @Override
    public void updateToken(SSOToken token) {
        try {
            logger.debug("更新令牌: {}", token.getAccessToken());
            if (token.getAccessToken() != null) {
                tokenStore.put(token.getAccessToken(), token);
            }
            if (token.getRefreshToken() != null) {
                refreshTokenStore.put(token.getRefreshToken(), token);
            }
        } catch (Exception e) {
            logger.error("更新令牌异常", e);
            throw new RuntimeException("更新令牌失败", e);
        }
    }
    
    @Override
    public boolean revokeToken(String accessToken) {
        try {
            logger.info("撤销令牌: {}", accessToken);
            SSOToken token = tokenStore.remove(accessToken);
            if (token != null && token.getRefreshToken() != null) {
                refreshTokenStore.remove(token.getRefreshToken());
            }
            return true;
        } catch (Exception e) {
            logger.error("撤销令牌异常", e);
            return false;
        }
    }
    
    @Override
    public boolean revokeUserTokens(String userId) {
        try {
            logger.info("撤销用户所有令牌，用户ID: {}", userId);
            int count = 0;
            
            // 撤销访问令牌
            Iterator<Map.Entry<String, SSOToken>> iterator = tokenStore.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, SSOToken> entry = iterator.next();
                if (userId.equals(entry.getValue().getUserId())) {
                    iterator.remove();
                    count++;
                }
            }
            
            // 撤销刷新令牌
            Iterator<Map.Entry<String, SSOToken>> refreshIterator = refreshTokenStore.entrySet().iterator();
            while (refreshIterator.hasNext()) {
                Map.Entry<String, SSOToken> entry = refreshIterator.next();
                if (userId.equals(entry.getValue().getUserId())) {
                    refreshIterator.remove();
                }
            }
            
            logger.info("撤销用户令牌完成，撤销数量: {}", count);
            return true;
        } catch (Exception e) {
            logger.error("撤销用户令牌异常", e);
            return false;
        }
    }
    
    @Override
    public int cleanExpiredTokens() {
        try {
            logger.info("开始清理过期令牌");
            int count = 0;
            
            // 清理过期的访问令牌
            Iterator<Map.Entry<String, SSOToken>> iterator = tokenStore.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, SSOToken> entry = iterator.next();
                if (entry.getValue().isExpired()) {
                    iterator.remove();
                    count++;
                }
            }
            
            // 清理过期的刷新令牌
            Iterator<Map.Entry<String, SSOToken>> refreshIterator = refreshTokenStore.entrySet().iterator();
            while (refreshIterator.hasNext()) {
                Map.Entry<String, SSOToken> entry = refreshIterator.next();
                if (entry.getValue().isExpired()) {
                    refreshIterator.remove();
                }
            }
            
            // 清理过期的授权码
            Iterator<Map.Entry<String, SSOToken>> authCodeIterator = authCodeStore.entrySet().iterator();
            while (authCodeIterator.hasNext()) {
                Map.Entry<String, SSOToken> entry = authCodeIterator.next();
                if (entry.getValue().isExpired()) {
                    authCodeIterator.remove();
                }
            }
            
            logger.info("清理过期令牌完成，清理数量: {}", count);
            return count;
        } catch (Exception e) {
            logger.error("清理过期令牌异常", e);
            return 0;
        }
    }
}